package ua.com.jpy.common.basic.dao;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bson.types.ObjectId;

import ua.com.jpy.entity.IEntity;

import com.google.code.morphia.DatastoreImpl;
import com.google.code.morphia.Morphia;
import com.google.code.morphia.dao.BasicDAO;
import com.google.code.morphia.query.Query;
import com.mongodb.Mongo;

/**
 * @author LSD25
 *
 */
public class JpyBasicDao<T, K> extends BasicDAO<T, K> implements IJpyBasicDao {
	
	private static final Log log = LogFactory.getLog(JpyBasicDao.class);

	protected JpyBasicDao(Mongo mongo, Morphia morphia, String dbName, String username, String password, boolean isAuthenticated) {
		super(new DatastoreImpl(morphia, mongo, dbName));
		if (isAuthenticated) {
			if (!this.ds.getDB().isAuthenticated() && !this.ds.getDB().authenticate(username, password.toCharArray())) {
				throw new RuntimeException("MongoDB authentication failed: " + dbName);
			}
		}
	}

	@Override
	public IEntity getOrCreate(IEntity entityForSave, ObjectId id) {
		if(entityForSave != null && id == null) {
			log.info("Save new entity to database");
			getDatastore().save(entityForSave);
			log.info("The entity was successfully save in database");
			return (IEntity) entityForSave;
		} else {
			if(entityForSave != null && id != null) {
				log.info("Find document with id: " + id + " in collection with name: " + ((IEntity) entityForSave).getClass().getName());
				Query<? extends IEntity> query = getDatastore().createQuery(((IEntity) entityForSave).getClass());
				query = query.field("id").equal(id);
				IEntity entity = (IEntity) query.get();
				if(entity == null) {
					log.info("Can not find document in collection: " + ((IEntity) entityForSave).getClass().getName());
					return null;
				} else {
					log.info("We found document with id: " + id + " in collection: " + entity.getClass().getName());
					return entity;
				}
			}
		}
		return null;
	}

	@Override
	public boolean delete(IEntity entityFoDelete, ObjectId id) {
		if(entityFoDelete == null) {
			log.info("The entityFoDelete is null");
			return false;
		}
		if(id == null) {
			log.info("id is null");
			return false;
		}
		Query<? extends IEntity> query = getDatastore().createQuery(entityFoDelete.getClass());
		getDatastore().delete(query);
		return true;
	}

	@Override
	public boolean update(IEntity entityForUpdate, ObjectId id) {
		if(entityForUpdate == null) {
			log.info("The entityForUpdate is null");
			return false;
		}
		if(id == null) {
			log.info("id is null");
			return false;
		}
		Query<? extends IEntity> query = getDatastore().createQuery(entityForUpdate.getClass());
		query = query.field("id").equal(id);
		IEntity entitySavedInDataBase = query.get();
		if(entitySavedInDataBase == null) {
			log.info("Entity with id: " + id + " not saved into database");
			return false;
		}
		log.info("Entity was successfuly finded");
		entityForUpdate.setId(id);
		getDatastore().delete(query);
		getDatastore().save(entityForUpdate);
		log.info("Update entity was successfull");
		return true;
	}

}
